<template>
  <div class="layer-search-container">
    <!-- 地图挂载容器 -->
    <div id="map" ref="map" class="map-container"></div>
    
    <!-- 控制面板 -->
    <div class="control-panel">
      <div class="panel-header">
        <h3>图层探查工具</h3>
        <button class="close-btn" @click="togglePanel">×</button>
      </div>
      
      <div class="panel-body">
        <!-- 图层选择 -->
        <div class="control-group">
          <label>探查图层：</label>
          <select v-model="selectedLayer" @change="updateLayerVisibility">
            <option value="osm">OpenStreetMap</option>
            <option value="tianditu">天地图影像</option>
          </select>
        </div>
        
        <!-- 探查形状 -->
        <div class="control-group">
          <label>探查形状：</label>
          <div class="shape-buttons">
            <button 
              :class="['shape-btn', {active: searchShape === 'circle'}]" 
              @click="searchShape = 'circle'">
              圆形
            </button>
            <button 
              :class="['shape-btn', {active: searchShape === 'square'}]" 
              @click="searchShape = 'square'">
              方形
            </button>
          </div>
        </div>
        
        <!-- 探查大小控制 -->
        <div class="control-group">
          <label>探查大小：{{ radius }}px</label>
          <input 
            type="range" 
            v-model.number="radius" 
            min="25" 
            max="200" 
            step="5" 
            @input="updateMap"/>
          <div class="keyboard-hint">
            <span>或使用 ↑↓ 方向键调整</span>
          </div>
        </div>
        
        <!-- 探查模式 -->
        <div class="control-group">
          <label>探查模式：</label>
          <div class="mode-buttons">
            <button 
              :class="['mode-btn', {active: searchMode === 'reveal'}]" 
              @click="searchMode = 'reveal'">
              显示探查区域
            </button>
            <button 
              :class="['mode-btn', {active: searchMode === 'hide'}]" 
              @click="searchMode = 'hide'">
              隐藏探查区域
            </button>
          </div>
        </div>
        
        <!-- 透明度控制 -->
        <div class="control-group">
          <label>图层透明度：{{ opacity * 100 }}%</label>
          <input 
            type="range" 
            v-model.number="opacity" 
            min="0.1" 
            max="1" 
            step="0.1" 
            @input="updateLayerOpacity"/>
        </div>
      </div>
    </div>
    
    <!-- 面板切换按钮 -->
    <button class="toggle-panel-btn" @click="togglePanel">
      {{ isPanelOpen ? '隐藏' : '显示' }}控制面板
    </button>
    
    <!-- 操作提示 -->
    <div class="operation-hint">
      <span>提示：移动鼠标探查图层，使用方向键调整探查大小</span>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue'
import { Map, View } from 'ol'              // 地图核心组件
import { OSM, XYZ } from 'ol/source'        // 数据源
import TileLayer from 'ol/layer/Tile'       // 瓦片图层
import { unByKey } from 'ol/Observable'     // 事件监听器管理

// 地图实例
const map = ref(null)
const mapRef = ref(null)

// 图层实例
const tiandiMapLayer = ref(null)
const osmLayer = ref(null)

// 探查相关状态
const radius = ref(75)                       // 探查半径
const mousePosition = ref(null)              // 鼠标位置
const selectedLayer = ref('osm')             // 当前选择的探查图层
const searchShape = ref('circle')            // 探查形状：circle(圆形)或square(方形)
const searchMode = ref('reveal')             // 探查模式：reveal(显示)或hide(隐藏)
const opacity = ref(1)                       // 图层透明度
const isPanelOpen = ref(true)                // 控制面板是否打开

// 事件监听器引用
let mapMoveListener = null
let mapOutListener = null
let keyDownListener = null
let prerenderListener = null
let postrenderListener = null

// 计算当前活动的探查图层
const activeLayer = computed(() => {
  return selectedLayer.value === 'osm' ? osmLayer.value : tiandiMapLayer.value
})

/**
 * 初始化地图
 */
const initMap = () => {
  // 创建天地图影像图层
  tiandiMapLayer.value = new TileLayer({
    name: '天地图影像图层',
    source: new XYZ({
      url: 'http://t0.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=9893433c99cfb657e6ec3a92fe4068e5'
    }),
    opacity: opacity.value
  })

  // 创建OpenStreetMap图层
  osmLayer.value = new TileLayer({
    name: 'OpenStreetMap',
    source: new OSM(),
    opacity: opacity.value
  })

  // 初始化地图实例
  map.value = new Map({
    target: 'map',
    layers: [tiandiMapLayer.value, osmLayer.value],
    view: new View({
      center: [113.24981689453125, 23.126468438108688], // 视图中心位置
      projection: 'EPSG:4326',                          // 投影方式
      zoom: 12                                          // 缩放级别
    })
  })

  // 初始化图层探查控制
  initLayerSearchControl()
}

/**
 * 初始化图层探查控制
 */
const initLayerSearchControl = () => {
  // 添加键盘事件监听
  keyDownListener = document.addEventListener('keydown', handleKeyDown)

  // 添加鼠标移动事件监听
  mapMoveListener = mapRef.value.addEventListener('mousemove', handleMouseMove)

  // 添加鼠标移出事件监听
  mapOutListener = mapRef.value.addEventListener('mouseout', handleMouseOut)

  // 设置图层渲染事件
  setupLayerRenderEvents()
}

/**
 * 设置图层渲染事件
 */
const setupLayerRenderEvents = () => {
  // 清除之前的事件监听器
  if (prerenderListener) {
    unByKey(prerenderListener)
  }
  if (postrenderListener) {
    unByKey(postrenderListener)
  }

  const layer = activeLayer.value
  if (!layer) return

  // 在渲染前进行裁剪
  prerenderListener = layer.on('prerender', handlePrerender)

  // 渲染后恢复画布
  postrenderListener = layer.on('postrender', handlePostrender)
}

/**
 * 处理键盘按下事件
 */
const handleKeyDown = (event) => {
  if (event.keyCode === 38) {
    // 上方向键：增加半径
    radius.value = Math.min(radius.value + 5, 200)
    updateMap()
    event.preventDefault()
  } else if (event.keyCode === 40) {
    // 下方向键：减小半径
    radius.value = Math.max(radius.value - 5, 25)
    updateMap()
    event.preventDefault()
  }
}

/**
 * 处理鼠标移动事件
 */
const handleMouseMove = (event) => {
  if (!map.value) return
  
  // 获取鼠标在地图上的像素位置
  mousePosition.value = map.value.getEventPixel(event)
  updateMap()
}

/**
 * 处理鼠标移出事件
 */
const handleMouseOut = () => {
  mousePosition.value = null
  updateMap()
}

/**
 * 处理图层渲染前事件
 */
const handlePrerender = (event) => {
  const ctx = event.context
  const pixelRatio = event.frameState.pixelRatio
  
  ctx.save()
  ctx.beginPath()
  
  if (mousePosition.value) {
    const x = mousePosition.value[0] * pixelRatio
    const y = mousePosition.value[1] * pixelRatio
    const r = radius.value * pixelRatio
    
    // 根据选择的形状绘制不同的探查区域
    if (searchShape.value === 'circle') {
      // 圆形探查区域
      ctx.arc(x, y, r, 0, 2 * Math.PI)
    } else {
      // 方形探查区域
      ctx.rect(x - r, y - r, r * 2, r * 2)
    }
    
    // 绘制边框
    ctx.lineWidth = 3 * pixelRatio
    ctx.strokeStyle = 'rgba(255, 102, 0, 0.7)'
    ctx.stroke()
    
    // 根据探查模式决定裁剪方式
    if (searchMode.value === 'reveal') {
      // 显示探查区域，隐藏其他区域
      ctx.clip()
    } else {
      // 隐藏探查区域，显示其他区域
      ctx.globalCompositeOperation = 'destination-out'
      if (searchShape.value === 'circle') {
        ctx.arc(x, y, r, 0, 2 * Math.PI)
      } else {
        ctx.rect(x - r, y - r, r * 2, r * 2)
      }
      ctx.fill()
      ctx.globalCompositeOperation = 'source-over'
    }
  } else if (searchMode.value === 'reveal') {
    // 没有鼠标位置时，默认隐藏整个图层
    ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height)
    ctx.clip()
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
  }
}

/**
 * 处理图层渲染后事件
 */
const handlePostrender = (event) => {
  const ctx = event.context
  ctx.restore()
}

/**
 * 更新图层可见性
 */
const updateLayerVisibility = () => {
  // 重新设置图层渲染事件
  setupLayerRenderEvents()
  updateMap()
}

/**
 * 更新图层透明度
 */
const updateLayerOpacity = () => {
  if (tiandiMapLayer.value) {
    tiandiMapLayer.value.setOpacity(opacity.value)
  }
  if (osmLayer.value) {
    osmLayer.value.setOpacity(opacity.value)
  }
  updateMap()
}

/**
 * 强制更新地图
 */
const updateMap = () => {
  if (map.value) {
    map.value.render()
  }
}

/**
 * 切换控制面板显示状态
 */
const togglePanel = () => {
  isPanelOpen.value = !isPanelOpen.value
}

/**
 * 组件挂载时初始化
 */
onMounted(() => {
  initMap()
})

/**
 * 组件卸载时清理资源
 */
onUnmounted(() => {
  // 移除事件监听器
  if (keyDownListener) {
    document.removeEventListener('keydown', keyDownListener)
  }
  if (mapMoveListener && mapRef.value) {
    mapRef.value.removeEventListener('mousemove', mapMoveListener)
  }
  if (mapOutListener && mapRef.value) {
    mapRef.value.removeEventListener('mouseout', mapOutListener)
  }
  
  // 移除OpenLayers事件监听器
  if (prerenderListener) {
    unByKey(prerenderListener)
  }
  if (postrenderListener) {
    unByKey(postrenderListener)
  }
  
  // 销毁地图实例
  if (map.value) {
    map.value.setTarget(null)
  }
})
</script>

<style scoped>
.layer-search-container {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.map-container {
  width: 100%;
  height: 100%;
  min-height: 450px;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  background-color: #f5f5f5;
}

/* 控制面板样式 */
.control-panel {
  position: absolute;
  top: 20px;
  left: 20px;
  width: 280px;
  background: white;
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  z-index: 1000;
  transition: all 0.3s ease;
  font-family: 'Microsoft YaHei', Arial, sans-serif;
}

.panel-header {
  padding: 15px 20px;
  border-bottom: 1px solid #f0f0f0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: linear-gradient(135deg, #008c8c 0%, #005a5a 100%);
  color: white;
  border-radius: 12px 12px 0 0;
}

.panel-header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 500;
}

.close-btn {
  background: none;
  border: none;
  color: white;
  font-size: 20px;
  cursor: pointer;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  transition: background-color 0.2s ease;
}

.close-btn:hover {
  background: rgba(255, 255, 255, 0.2);
}

.panel-body {
  padding: 20px;
}

.control-group {
  margin-bottom: 20px;
}

.control-group:last-child {
  margin-bottom: 0;
}

.control-group label {
  display: block;
  margin-bottom: 8px;
  font-weight: 500;
  color: #333;
  font-size: 14px;
}

.control-group select {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 6px;
  font-size: 14px;
  background: white;
  transition: border-color 0.3s ease;
}

.control-group select:focus {
  outline: none;
  border-color: #008c8c;
}

.control-group input[type="range"] {
  width: 100%;
  margin: 8px 0;
}

/* 形状和模式按钮组 */
.shape-buttons, .mode-buttons {
  display: flex;
  gap: 8px;
}

.shape-btn, .mode-btn {
  flex: 1;
  padding: 8px 12px;
  border: 2px solid #ddd;
  background: white;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  transition: all 0.3s ease;
}

.shape-btn:hover, .mode-btn:hover {
  border-color: #008c8c;
}

.shape-btn.active, .mode-btn.active {
  background: #008c8c;
  color: white;
  border-color: #008c8c;
}

/* 键盘提示 */
.keyboard-hint {
  font-size: 12px;
  color: #666;
  text-align: center;
  margin-top: 4px;
}

/* 面板切换按钮 */
.toggle-panel-btn {
  position: absolute;
  bottom: 20px;
  left: 20px;
  padding: 8px 16px;
  background: white;
  border: 1px solid #ddd;
  border-radius: 20px;
  cursor: pointer;
  font-size: 13px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.3s ease;
  z-index: 1000;
}

.toggle-panel-btn:hover {
  background: #f8f9fa;
  border-color: #008c8c;
}

/* 操作提示 */
.operation-hint {
  position: absolute;
  bottom: 20px;
  right: 20px;
  padding: 8px 16px;
  background: rgba(0, 0, 0, 0.7);
  color: white;
  border-radius: 6px;
  font-size: 13px;
  z-index: 1000;
  backdrop-filter: blur(2px);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .control-panel {
    width: 240px;
    top: 10px;
    left: 10px;
  }
  
  .panel-body {
    padding: 15px;
  }
  
  .map-container {
    min-height: 350px;
  }
  
  .toggle-panel-btn {
    bottom: 10px;
    left: 10px;
    font-size: 12px;
    padding: 6px 12px;
  }
  
  .operation-hint {
    bottom: 10px;
    right: 10px;
    font-size: 11px;
    padding: 6px 12px;
  }
}
</style>